﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using SEOLib;

namespace ApiScanner.Core
{
    public sealed class SmtpServerEventScanner: IScanner
    {
        private static readonly IEnumerable<string> MicrosoftSinkProgIds = new[]
                                                                               {
                                                                                   "CDO2EventSink.IsmSink1",
                                                                                   "Exchange.Categorizer",
                                                                                   "Exchange.ExchangeDrv",
                                                                                   "Exchange.LoadBalancer",
                                                                                   "Exchange.MisCat",
                                                                                   "Exchange.NtfsDrv",
                                                                                   "Exchange.ProtoLog",
                                                                                   "Exchange.PS-Ehlo",
                                                                                   "Exchange.PS-EOD",
                                                                                   "Exchange.PS-EXPS",
                                                                                   "Exchange.PS-EXPSAux",
                                                                                   "Exchange.PS-Mail",
                                                                                   "Exchange.Router",
                                                                                   "Exchange.TransportAVAPI",
                                                                                   "MSExchange.ContentFilterSink",
                                                                                   "MsgTrackLog",
                                                                                   "NNTP.DirectoryDrop",
                                                                                   "peexch50.ehlo",
                                                                                   "peexch50.exch50",
                                                                                   "peexch50.rcptto",
                                                                                   "peexch50.submit",
                                                                                   "Sink.XLSA",
                                                                                   "tranmsg.EventSink",
                                                                                   "TurfList.TurfList",
                                                                                   "peexch50.mail"
                                                                               };

        public void Initialize(TestConfigurationElement configuration)
        {
        }

        public IEnumerable<Artifact> EnumerateArtifacts(Action<string> progressHandler)
        {
            var type = Type.GetTypeFromProgID("Event.Manager", true);
            var eventManager = (IEventManager) Activator.CreateInstance(type);

            try
            {
                foreach (var eventSource in eventManager.SourceTypes.ComEnumerate<IEventSourceType>())
                {
                    foreach (var source in eventSource.Sources.ComEnumerate<IEventSource>())
                    {
                        var bindingManager = source.GetBindingManager();
                        try
                        {
                            foreach (var eventType in eventSource.EventTypes.ComEnumerate<IEventType>())
                            {
                                foreach (var binding in bindingManager.get_Bindings(eventType.ID).ComEnumerate<IEventBinding>())
                                {
                                    if (IsDefaultBinding(binding)) continue;
                                    yield return
                                        new SmtpServerEventBinding(binding.get_DisplayName(), binding.get_SinkClass());
                                }
                            }
                        }
                        finally
                        {
                            Marshal.ReleaseComObject(bindingManager);
                        }
                    }
                }
            }
            finally
            {
                Marshal.ReleaseComObject(eventManager);
            }
        }


        private static bool IsDefaultBinding(IEventBinding binding)
        {
            return MicrosoftSinkProgIds.Contains(binding.get_SinkClass());
        }
    }
}
